package com.matrix.basecore.utils.glide;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Build;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RSRuntimeException;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;

import androidx.annotation.NonNull;

import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;

import java.security.MessageDigest;

public class BlurTransformer extends BitmapTransformation {
    private static final int VERSION = 1;
    private static final String ID ="jp.wasabeef.glide.transformations.BlurTransformation." + VERSION;

    private static final int MAX_RADIUS = 25;

    private static final int DEFAULT_DOWN_SAMPLING = 1;

    private final int radius;

    private final int sampling;
    private Context mContext;
    public BlurTransformer(Context context) {
        this(context,MAX_RADIUS, DEFAULT_DOWN_SAMPLING);
        mContext=context;

    }

    public BlurTransformer(Context context, int radius) {
        this(context,radius, DEFAULT_DOWN_SAMPLING);
        mContext=context;
    }

    public BlurTransformer(Context context,int radius, int sampling) {
        mContext=context;
        this.radius = radius;
        this.sampling = sampling;
    }

    @Override
    protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {

        int width = toTransform.getWidth();

        int height = toTransform.getHeight();

        int scaledWidth = width / sampling;

        int scaledHeight = height / sampling;

        Bitmap bitmap = pool.get(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888);
//        setCanvasBitmapDensity(toTransform, bitmap);

        Canvas canvas = new Canvas(bitmap);
        canvas.scale(1 / (float) sampling, 1 / (float) sampling);
        Paint paint = new Paint();
        paint.setFlags(Paint.FILTER_BITMAP_FLAG);

        canvas.drawBitmap(toTransform, 0, 0, paint);
        try {
            bitmap = blur(mContext, bitmap, radius);
        } catch (Exception e) {

        }
        return bitmap;
    }

    @Override
    public int hashCode() {
        return ID.hashCode() + radius * 1000 + sampling * 10;
    }

    @Override

    public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {

        messageDigest.update((ID + radius + sampling).getBytes(CHARSET));

    }
    public static Bitmap blur(Context context, Bitmap bitmap, int radius) throws RSRuntimeException {
        RenderScript rs = null;
        Allocation input = null;
        Allocation output = null;
        ScriptIntrinsicBlur blur = null;
        try {
            rs = RenderScript.create(context);
            rs.setMessageHandler(new RenderScript.RSMessageHandler());
            input = Allocation.createFromBitmap(rs, bitmap, Allocation.MipmapControl.MIPMAP_NONE,
                    Allocation.USAGE_SCRIPT);
            output = Allocation.createTyped(rs, input.getType());
            blur = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));

            blur.setInput(input);
            blur.setRadius(radius);
            blur.forEach(output);
            output.copyTo(bitmap);
        } finally {
            if (rs != null) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    RenderScript.releaseAllContexts();
                } else {
                    rs.destroy();
                }
            }
            if (input != null) {
                input.destroy();
            }
            if (output != null) {
                output.destroy();
            }
            if (blur != null) {
                blur.destroy();
            }
        }

        return bitmap;
    }
}
